#pragma once

#include <string>

// ===========================================================
// [目的] 例：
//      已知代码: #inc
//      则经过 ErrorOutput 处理后应输出下面字符串:
//          #inc                // 说明：原文
//           ^~~                // 说明：错误发生地
//          invalid preprocessing directive #inc    // 说明：错误信息
// ===========================================================

namespace header
{

using col_t = unsigned int;

constexpr char ERROR_BEGIN = '^';
constexpr char ERROR_END   = '~'; 

class Error
{
public:
    Error(const std::string& s, const std::string& w, col_t b, col_t e)
        :_source{ s }, _what{ w }, _begin{ b }, _end{ e }
    {
        if (_begin > _end) _end = _begin;
        auto len = s.size();
        if (_begin > len) _begin = len;     // 原文末尾
        if (_end > len) _end = len;         // 原文末尾
    }

public:
    std::string source() const { return _source; }
    std::string what() const { return _what; }
    col_t begin() const { return _begin; }
    col_t end() const { return _end; }
    
private:
    std::string _source;     // 原文
    std::string _what;       // 错误信息
    col_t       _begin;      // 错误发生在原文所在开始列号 (从 0 开始)
    col_t       _end;        // 错误发生在原文所在结束列号 (从 0 开始)
};

class ErrorOutput
{
public:
    static std::string deal(const Error& error);
};

std::string ErrorOutput::deal(const Error& error)
{
    std::string res = error.source();
    res += "\n" + std::string(error.begin(), ' ');
    res.push_back(ERROR_BEGIN);
    res += std::string(error.end() - error.begin(), ERROR_END);
    res += "\n" + std::string(error.begin(), ' ') + error.what();
    return res;
}

}   // namespace header
